package com.choudou5.solr.web.handler.sys;

import cn.hutool.core.util.NumberUtil;
import com.choudou5.solr.annotation.ReqMapping;
import com.choudou5.solr.annotation.ReqMethod;
import com.choudou5.solr.framework.bean.UserBean;
import com.choudou5.solr.framework.bean.UserSessionBean;
import com.choudou5.solr.framework.constants.ErrorResp;
import com.choudou5.solr.framework.constants.SysConsts;
import com.choudou5.solr.framework.constants.UserConsts;
import com.choudou5.solr.framework.holder.SessionContextHolder;
import com.choudou5.solr.framework.util.LoginUtil;
import com.choudou5.solr.framework.util.PageJumpUtil;
import com.choudou5.solr.framework.util.RequestUtil;
import com.choudou5.solr.framework.util.UserUtil;
import com.choudou5.solr.util.*;
import com.choudou5.solr.utils.PasswordUtil;
import com.choudou5.solr.utils.oauth.OauthRespBean;
import com.choudou5.solr.utils.oauth.OauthUtil;
import com.choudou5.solr.web.handler.BaseHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Name：登录处理器
 * @Author：choudou5
 * @Date：2018-07-14
 */
public class LoginHandler extends BaseHandler {


    @Override
    public void execute(String method, HttpServletRequest req, HttpServletResponse resp) {
        logger.info("LoginHandler method:{}", method);
        String ip = IpUtil.getRealIpAddr(req);
        switch (method){
            case "getPubKey":
                getPubKey(ip, req, resp);
                break;
            case "in":
                login(ip, req, resp);
                break;
            case "out":
                loginOut(req, resp);
                break;
            case "oauth": //通过 配置的外部接口 返回合法与ip 来自动注册
                oauth(ip, req, resp);
                break;
            default:
                PageJumpUtil.errorOut(ErrorResp.Not_Found, req, resp);
                break;
        }
    }


    @ReqMapping(desc = "获取公钥", method = ReqMethod.POST)
    private void getPubKey(String ip, HttpServletRequest req, HttpServletResponse resp){
        String pubKey = LoginRsaUtil.getPubKey();
//        https://blog.csdn.net/chen_3010/article/details/71440754
        PageJumpUtil.writeJsonObjOk(pubKey, resp);
    }

    /**
     * 登录
     * @param req
     * @param resp
     */
    @ReqMapping(desc = "登录", method = ReqMethod.POST)
    private void login(String ip, HttpServletRequest req, HttpServletResponse resp){
        String phoneStr = RequestUtil.getStrParameter(req, "phone");
        String pwd = RequestUtil.getStrParameter(req, "sigPwd");
        if (phoneStr == null) {
            PageJumpUtil.writeJsonInvalidParam("请输入正确格式手机号", resp);
            return;
        }
        phoneStr = LoginRsaUtil.decrypt(phoneStr);
        if (phoneStr.length() != 11 && NumberUtil.isLong(phoneStr)) {
            PageJumpUtil.writeJsonInvalidParam("请输入11位的手机号", resp);
            return;
        }
        Long phone = Long.parseLong(phoneStr);
        //校验毫秒重试次数
        if(!LoginUtil.checkFailLoginCount(phone)){
            PageJumpUtil.writeJson(ErrorResp.Block_Login, "您的手机号登录失败次数太多，请5分钟后再试！", resp);
            //钉钉通知
            return;
        }
        pwd = LoginRsaUtil.decrypt(pwd);
        if (StrUtil.isBlank(pwd) || pwd.length() > 15) {
            PageJumpUtil.writeJsonInvalidParam("用户或密码错误, 请重试", resp);
            LoginUtil.recordFailLogin(phone);
            return;
        }
        // 校验用户名密码
        UserBean user = sysUserService.getByPhone(phone);
        if (user == null) {
            PageJumpUtil.writeJsonInvalidParam("用户或密码错误", resp);
            LoginUtil.recordFailLogin(phone);
            return;
        }
        if (UserConsts.UserStatus.DISABLE.eq(user.getStatus())){
            PageJumpUtil.writeJsonInvalidParam("该已帐号禁止登录", resp);
            LoginUtil.recordFailLogin(phone);
            return;
        }
        String password = user.getPassword();
        if (StrUtil.isBlank(password)){
            PageJumpUtil.writeJsonInvalidParam(phone + " 用户密码为空, 请联系管理员", resp);
            LoginUtil.recordFailLogin(phone);
            return;
        }
        if(!PasswordUtil.validate(user.getId(), user.getPassword(), pwd)){
            PageJumpUtil.writeJsonInvalidParam(phone + " 账号密码有误", resp);
            LoginUtil.recordFailLogin(phone);
            return;
        }
        LoginUtil.removeFailLogin(phone);//移除失败登录记录
        //登录成功处理
        loginSuccTodo(ip, user, req, resp);
    }

    private void loginSuccTodo(String ip, UserBean user, HttpServletRequest req, HttpServletResponse resp){
        String token = LoginUtil.genToken(ip);
        sysUserService.loginSucc(user, ip);
        UserSessionBean sessionBean = BeanMapper.map(user, UserSessionBean.class);
        sessionBean.setToken(token);
        SessionContextHolder.setParam(token, UserConsts.USER_BEAN_SESSION_KEY, sessionBean);
        CookieUtil.setCookie(resp, SysConsts.HEADER_TOKEN, token);
        PageJumpUtil.writeJsonOk("登录成功", resp);
    }

    /**
     * 退出
     * @param req
     * @param resp
     */
    private void loginOut(HttpServletRequest req, HttpServletResponse resp){
        UserSessionBean user = UserUtil.getUser();
        if(user != null){
            sysUserService.loginOut(user);
            CookieUtil.removeCookie(resp, SysConsts.HEADER_TOKEN);
        }
        PageJumpUtil.forward(SysConsts.PAGE_LOGIN, req, resp);
    }


    @ReqMapping(desc = "第三方认证登录", method = ReqMethod.POST)
    private void oauth(String ip, HttpServletRequest req, HttpServletResponse resp){
        String token = RequestUtil.getStrParameter(req, "token");
        String appId = RequestUtil.getStrParameter(req, "appId");
        Long phone = RequestUtil.getPhoneParameter(req, "phone");
        if(validParam(req, resp, new Object[]{appId, phone}, new String[]{"appId", "手机号"})){
            //不存在 则去第三方校验
            OauthRespBean oauthResp = OauthUtil.getOauthResp(token, appId, phone, ip);
            if(oauthResp == null){
                PageJumpUtil.writeJson(ErrorResp.Forbidden, "号码认证不通过，请确认是否有效", resp);
                return;
            }
            //第三方系统不通过
            if(!oauthResp.getStatusCode().equals(200)){
                PageJumpUtil.writeJson(ErrorResp.Forbidden, "号码认证不通过，"+oauthResp.getMessage(), resp);
                return;
            }

            UserBean userBean = sysUserService.getByPhone(phone);
            //用户已存在
            if(userBean != null){
                //登录成功处理
                loginSuccTodo(ip, userBean, req, resp);
                return;
            }
            //注册
            userBean = sysUserService.registerByOauth(oauthResp.getUserName(), ip);
            //登录成功处理
            loginSuccTodo(ip, userBean,  req, resp);
        }
    }

}
